﻿include System
include System::Net 
include System::Windows
include System::Windows::Controls 
include System::Windows::Input 
include System::Windows::Media 
include System::Windows::Shapes
include System::Windows::Media::Animation 
include System::Windows::Media::Imaging 
include System::Windows::Browser
include System::Diagnostics  
include System::Windows::Markup   
include System::Collections::Generic  
include System::Collections::ObjectModel  
include System::Windows::Threading

# must be ARGB format
ButtonOffHexValue = "#ffbbbbbb" # color of buttons when mouse is not over
ButtonOverHexValue = "#ffeeeeee" # color of buttons when mouse is hovering
PanelBackgroundHexValue = "#44ffffff" # The control panel background color
TextColorHexValue = "#ff808080" # the color of the timecode and caption
MediaBackDropHexValue = "#ff000000" # the color of the overall media player background

@isScrubberLocked = false
@positionTimer = DispatcherTimer.new
@loop = false
@src = ""
@poster = ""
@volume = 0.5
@width = 300
@height = 150
@autoPlay = true
@muted = false
@controls = false
@autoBuffer = false
@ended = false

	#Holds the video 
	class SourceElement 
	  attr_accessor :type, :src
	  src = ""
	  type = ""
	  
	end

	#List that holds each video as a SourceElement with methods to access each video on the list.
	class SelectableSourceElementList < System::Collections::Generic::List[SourceElement]
		
		def initialize
			@clrclassattribs = []
			@lastItem = true
			self.selectedIndex = 0
		end
		
		attr_accessor :selectedIndex
		attr_accessor :SelectedItem
		
		def nextVideo
			self.selectedIndex = self.selectedIndex + 1
        
			if (self.selectedIndex + 1) > self.count
				self.selectedIndex = 0
				@lastItem = true
			else
				@lastItem = false
            end
		end
		
		def previous
			self.selectedIndex = self.selectedIndex - 1
			
			if self.selectedIndex < 0
				self.selectedIndex = self.count - 1
            end
		end
		
		def getSelectedItem
			if self[self.selectedIndex] != nil 
				return self[self.selectedIndex]
			else
				return nil
			end
		end
	end

#Converts Hex values to ARGB values
def ConvertHexToColor(hexColor)
    @c = Color.new
	@c = Color.FromArgb(Convert.to_u_int_32(hexColor[1,2].to_i(16)),
	Convert.to_u_int_32(hexColor[3,2].to_i(16)),
	Convert.to_u_int_32(hexColor[5,2].to_i(16)), 
	Convert.to_u_int_32(hexColor[7,2].to_i(16)))
end

#Checks the filepath to ensure correct format.
def ensureAbsoluteFilePath(initialPath)
	path = ""
	if String.IsNullOrEmpty(initialPath)
		return String.empty
	end
	if initialPath.downcase.include?("http://")
		return initialPath
	else
		s = domGetFullPathToDir()
		return s << initialPath
	end

end

def domGetFullPathToDir()
	@content = ""
	begin
		path = HtmlPage.Document.DocumentUri.ToString
		segments = path.Split('/')
		@content = path.Replace(segments[segments.Length - 1], "")
	end
	rescue
end

#Plays a video
def play
	if me.Player.current_state != MediaElementState.Playing
		me.Poster.visibility = Visibility.Collapsed
		if MediaCollection.Count > 0
			if me.Player.position.total_seconds == 0
				me.Player.source = Uri.new(MediaCollection.getSelectedItem.src, UriKind.Absolute)
				me.Caption.text = ""
			end
		end
		if me.Player.auto_play == false
			me.Player.MediaOpened{ |s, e| opened(s, e) }
		else
			if me.Player.current_state != MediaElementState.Playing
				me.Player.play
			end
		end
	end
end

#Plays a video 
def opened (sender, event_args)
	me.Player.play
end

#Plays the next source element.
def nextVideo
	me.Player.pause
	me.Player.position = TimeSpan.new(0,0,0)
	if MediaCollection.count > 1
		MediaCollection.nextVideo
	end
	play
end

def stop
	me.Poster.visibility = Visibility.visible
end

#Plays a previous SourceElement.
def previous
	me.Player.pause
	me.Player.position = TimeSpan.new(0,0,0)
	if MediaCollection.count > 1
		MediaCollection.previous
	end
	play
end

# define event handlers

#Shows the current position of the file being played on scrubber.
def positionTimer_tick (sender, event_args)
    if me.Player.position.total_seconds > 0 && @isScrubberLocked == false
        me.Scrubber.value = Convert.ToDouble(me.Player.Position.Ticks) / Convert.ToDouble(me.Player.NaturalDuration.TimeSpan.Ticks)
        me.MsgCurrentTime.text = System::String.Format("{0:00}:{1:00}:{2:00}", me.Player.Position.Hours, me.Player.Position.Minutes, me.Player.Position.Seconds)
	end
end

me.Player.media_opened do |sender, event_args| 
    me.Scrubber.value = 0
    me.MsgTotalTime.text = System::String.Format("{0:00}:{1:00}:{2:00}", me.Player.NaturalDuration.TimeSpan.Hours, me.Player.NaturalDuration.TimeSpan.Minutes, me.Player.NaturalDuration.TimeSpan.Seconds)
end

#Changes player UI based on state of media. 
me.Player.current_state_changed do |sender, event_args|
    if me.Player.current_state == MediaElementState.Playing
        me.ShowPauseButton.begin
        @positionTimer.start
    elsif me.Player.current_state == MediaElementState.Paused
        me.ShowPlayButton.begin
        @positionTimer.stop
    end   
    if me.Player.current_state == MediaElementState.Stopped
        me.ShowPlayButton.begin
        @positionTimer.stop
		me.Scrubber.value = 0
    end
end

me.Player.download_progress_changed do |sender, event_args|
    me.DownloadProgressTrack.RenderTransform.ScaleX = me.Player.DownloadProgress # Slider does not have this property
end

#Occurs when the mouse left button is pressed over the Poster image.
me.Poster.mouse_left_button_down do |sender, event_args|
	play
end

#Occurs when the mouse leaves the bounding area of the Scrubber.
me.Scrubber.mouse_leave do |sender, event_args|
    @isScrubberLocked = false
end

#Occurs when the mouse enters the bounding area of the Scrubber.
me.Scrubber.mouse_enter do |sender, event_args|
    @isScrubberLocked = true
end

#Occurs when the left mouse button is released over the Scrubber.
me.Scrubber.mouse_left_button_up do |sender, event_args|
    me.Player.position = TimeSpan.FromSeconds(me.Scrubber.value * me.Player.NaturalDuration.TimeSpan.TotalSeconds)
    @isScrubberLocked = false
end

me.BtnPlayPause.mouse_enter do |sender, event_args|
	me.PlayPauseSymbol_MouseEnter.begin()
end

me.BtnPlayPause.mouse_leave do |sender, event_args|
	me.PlayPauseSymbol_MouseLeave.begin()
end

me.BtnPlayPause.mouse_left_button_up do |sender, event_args|
    if me.Player.current_state == MediaElementState.Playing
        me.Player.pause
    elsif me.Player.current_state == MediaElementState.Paused
        play
    elsif me.Player.current_state == MediaElementState.Stopped
        play
	end
end

me.VolumeSlider.value_changed do |sender, event_args|
    me.Player.volume = me.VolumeSlider.value
end

me.ShowVolumeSlider.completed do |sender, event_args|
    me.VolumeSliderTimer.begin
end

me.ShowControlPanel.completed do |sender, event_args|
    me.ControlPanelTimer.begin
end

me.ControlPanelTimer.completed do |sender, event_args| 
	me.HideControlPanel.begin
end

me.ControlPanel.mouse_move do |sender, event_args| 
	if me.video.items[0]
		me.ShowControlPanel.begin
	end
end

me.Player.mouse_move do |sender, event_args| 
	if me.video.items[0]
		me.ShowControlPanel.begin
	end
end

me.Player.mouse_leave do |sender, event_args| 
	me.ControlPanelTimer.begin
end


me.VolumeSliderCanvas.mouse_move do |sender, event_args|
    me.VolumeSliderTimer.begin
end

me.VolumeSliderTimer.completed do |sender, event_args|
    me.HideVolumeSlider.begin
end

#Occurs when the left mouse button is released over the BtnVolume.
me.BtnVolume.mouse_left_button_up do |sender, event_args|
    me.ShowVolumeSlider.begin
end

#Occurs when the mouse enters the bounding area of the BtnVolume.   
me.BtnVolume.mouse_enter do |sender, event_args|
    me.VolumeSymbol_MouseEnter.begin  
end	

#Occurs when the mouse leaves the bounding area of the Scrubber.    
me.BtnVolume.mouse_leave do |sender, event_args|   
    me.VolumeSymbol_MouseLeave.begin 
end	

#Occurs when the mouse enters the bounding area of the NextSymbol.
me.NextSymbol.mouse_enter do |sender, event_args| 
	me.NextSymbol_MouseEnter.begin
end

#Occurs when the mouse leaves the bounding area of the NextSymbol.
me.NextSymbol.mouse_leave do |sender, event_args| 
	me.NextSymbol_MouseLeave.begin
end

#Occurs when the mouse enters the bounding area of the PreviousSymbol.
me.PreviousSymbol.mouse_enter do |sender, event_args| 
	me.PreviousSymbol_MouseEnter.begin
end

#Occurs when the mouse leaves the bounding area of the PreviousSymbol.
me.PreviousSymbol.mouse_leave do |sender, event_args|  
	me.PreviousSymbol_MouseLeave.begin
end

#Occurs when the mouse enters the bounding area of the FullSymbol.
me.FullSymbol.mouse_enter do |sender, event_args| 
	me.FullSymbol_MouseEnter.begin
end

#Occurs when the mouse leaves the bounding area of the FullSymbol.
me.FullSymbol.mouse_leave do |sender, event_args| 
	me.FullSymbol_MouseLeave.begin
end

me.Player.marker_reached do |sender, event_args| 
	me.Caption.text = event_args.Marker.text
end

#Occurs when the mouse left button is pressed over this UI element.
me.FullSymbol.mouse_left_button_down do |sender, event_args| 
	Application.Current.Host.Content.IsFullScreen =  !Application.Current.Host.Content.IsFullScreen
    me.Width = Application.Current.Host.Content.ActualWidth
    me.Height = Application.Current.Host.Content.ActualHeight
end
    
Application.Current.Host.Content.resized do |sender, event_args| 
    me.Width = Application.Current.Host.Content.ActualWidth
    me.Height = Application.Current.Host.Content.ActualHeight
end

#Occurs when the video ends.  Plays the next video, if possible.
me.Player.media_ended do |sender, event_args|
    me.Player.position = TimeSpan.new(0,0,0)
    me.Poster.visibility = Visibility.Collapsed
    
    if MediaCollection.Count > 0: # is there a playlist?
        if @loop # just keep looping
            MediaCollection.nextVideo
            play
        else
            MediaCollection.nextVideo
            if MediaCollection.selectedIndex > 0 # check to see if we've finished the playlist
                play
            else
                stop
			end
		end
    elsif @loop
        play
    else
        stop
	end
end

#Occurs when the player is unable to play a video.
me.Player.media_failed do |sender, event_args|
	me.Scrubber.value = 0 			#added to force scrubber back to reset position when no video is playing
    me.Caption.Text = "File not found: " + MediaCollection.getSelectedItem.src
    #HtmlPage.Window.Invoke("error", s, e)
end	
 
#Occurs when the left mouse button is released over the PreviousSymbol.
#Plays the previous video.
me.PreviousSymbol.mouse_left_button_down do |sender, event_args|
    previous
end

#Occurs when the left mouse button is released over the NextSymbol.
#Plays the next video.
me.NextSymbol.mouse_left_button_down do |sender, event_args|
    nextVideo
end	

#Sets colors of player
fillColor = SolidColorBrush.new(ConvertHexToColor(ButtonOffHexValue))
me.PlaySymbol.fill = fillColor 
me.PauseSymbol.fill = fillColor
me.SpeakerShape.fill = fillColor
me.VolumeShape1.stroke = fillColor
me.VolumeShape2.stroke = fillColor
me.NextA.fill = fillColor
me.NextB.fill = fillColor
me.PreviousA.fill = fillColor
me.PreviousB.fill = fillColor
me.FullA.fill = fillColor
me.FullB.fill = fillColor
me.FullC.fill = fillColor
me.FullD.fill = fillColor

background = SolidColorBrush.new(ConvertHexToColor(PanelBackgroundHexValue))
me.VolumeSliderBackground.fill = background
me.ControlPanelBackground.fill = background
foreground = SolidColorBrush.new(ConvertHexToColor(TextColorHexValue))
me.MsgCurrentTime.Foreground = foreground
me.Caption.Foreground = foreground
me.TimeDivider.Foreground = foreground
me.MsgTotalTime.Foreground = foreground
backdrop = SolidColorBrush.new(ConvertHexToColor(MediaBackDropHexValue))
me.MediaBackground.fill = backdrop
me.LayoutRoot.Background = backdrop


# set the storyboard To values for mouseleave events
buttonOffHexValue = ConvertHexToColor(ButtonOffHexValue) 
me.Stop_MouseLeaveValue.to = buttonOffHexValue
me.Play_MouseLeaveValue.to = buttonOffHexValue
me.Pause_MouseLeaveValue.to = buttonOffHexValue
me.Volume_MouseLeaveValue.to = buttonOffHexValue
me.Volume1_MouseLeaveValue.to = buttonOffHexValue
me.Volume2_MouseLeaveValue.to = buttonOffHexValue
me.NextA_MouseLeaveValue.to = buttonOffHexValue
me.NextB_MouseLeaveValue.to = buttonOffHexValue
me.PreviousA_MouseLeaveValue.to = buttonOffHexValue
me.PreviousB_MouseLeaveValue.to = buttonOffHexValue
me.FullA_MouseLeaveValue.to = buttonOffHexValue
me.FullB_MouseLeaveValue.to = buttonOffHexValue
me.FullC_MouseLeaveValue.to = buttonOffHexValue
me.FullD_MouseLeaveValue.to = buttonOffHexValue           

# set the storyboard to values for mouseenter events
buttonOverHexValue = ConvertHexToColor(ButtonOverHexValue)
me.Stop_MouseEnterValue.to = buttonOverHexValue
me.Play_MouseEnterValue.to = buttonOverHexValue
me.Pause_MouseEnterValue.to = buttonOverHexValue
me.Volume_MouseEnterValue.to = buttonOverHexValue
me.Volume1_MouseEnterValue.to = buttonOverHexValue
me.Volume2_MouseEnterValue.to = buttonOverHexValue
me.NextA_MouseEnterValue.to = buttonOverHexValue
me.NextB_MouseEnterValue.to = buttonOverHexValue
me.PreviousA_MouseEnterValue.to = buttonOverHexValue
me.PreviousB_MouseEnterValue.to = buttonOverHexValue
me.FullA_MouseEnterValue.to = buttonOverHexValue
me.FullB_MouseEnterValue.to = buttonOverHexValue
me.FullC_MouseEnterValue.to = buttonOverHexValue
me.FullD_MouseEnterValue.to = buttonOverHexValue

#timer for UI updates
@positionTimer = DispatcherTimer.new
@positionTimer.interval = TimeSpan.new(100)
@positionTimer.tick{ |s, e| positionTimer_tick(s, e) }
@positionTimer.start

@loop = me.loop.items[0]
#me.Width = me.width.items[0]
#me.Height = me.height.items[0]
me.Poster.source = BitmapImage.new(Uri.new(ensureAbsoluteFilePath(me.poster.items[0]), UriKind.RelativeOrAbsolute))

ap = me.autoplay.items[0]
me.Player.auto_play = ap

if !ap
	me.Poster.visibility = Visibility.Visible
end

me.Player.volume = me.volume.items[0]
me.Player.is_muted = @muted #me.muted.items[0]	
	
if !me.controls.items[0]
    me.ControlPanel.visibility = Visibility.Collapsed
end
    
if !me.video.items[0]
    me.Player.visibility = Visibility.Collapsed
    me.LayoutRoot.row_definitions[0].height = GridLength(0)
    me.MediaBackground.visibility = Visibility.Collapsed 
    me.Poster.visibility = Visibility.Collapsed
    me.ControlPanel.opacity = 1
end

#Creates a new SelectableSourceElementList and populates with SourceElements (videos)
#from the xaml file.
MediaCollection = SelectableSourceElementList.new
( 0...me.videos.items.Count).each do |i|
    s = SourceElement.new
    s.src = ensureAbsoluteFilePath(me.videos.items[i])
    MediaCollection.add(s)
end

me.Player.source = Uri.new(MediaCollection.getSelectedItem.src, UriKind.RelativeOrAbsolute)
